package 面向对象;

//在Java中，我们经常看到public、protected、private这些修饰符。在Java中，这些修饰符可以用来限定访问作用域。
//
//《public》
//定义为public的class、interface可以被其他任何类访问：
//
//package abc;
//
//public class Hello {
//    public void hi() {
//    }
//}
//上面的Hello是public，因此，可以被其他包的类访问：
//
//package xyz;
//
//class Main {
//    void foo() {
//        // Main可以访问Hello
//        Hello h = new Hello();
//    }
//}
//定义为public的field、method可以被其他类访问，前提是首先有访问class的权限：
//
//package abc;
//
//public class Hello {
//    public void hi() {
//    }
//}
//上面的hi()方法是public，可以被其他类调用，前提是首先要能访问Hello类：
//
//package xyz;
//
//class Main {
//    void foo() {
//        Hello h = new Hello();
//        h.hi();
//    }
//}

//《private》
//定义为private的field、method无法被其他类访问：
//
//package abc;
//
//public class Hello {
//    // 不能被其他类调用:
//    private void hi() {
//    }
//
//    public void hello() {
//        this.hi();
//    }
//}
//实际上，确切地说，private访问权限被限定在class的内部，而且与方法声明顺序无关。推荐把private方法放到后面，因为public方法定义了类对外提供的功能，
//阅读代码的时候，应该先关注public方法：
//
//package abc;
//
//public class Hello {
//    public void hello() {
//        this.hi();
//    }
//
//    private void hi() {
//    }
//}

//定义在一个class内部的class称为嵌套类（nested class），Java支持好几种嵌套类。
//由于Java支持嵌套类，如果一个类内部还定义了嵌套类，那么，嵌套类拥有访问private的权限：

/*public class 作用域 {
	public static void main(String[] args) {
		Inner i = new Inner();
		i.hi();
	}

	// private方法:
	private static void hello() {
		System.out.println("private hello!");
	}

	// 静态内部类:
	static class Inner {
		public void hi() {
			作用域.hello();
		}
	}
}*/


//《protected》
//protected作用于继承关系。定义为protected的字段和方法可以被子类访问，以及子类的子类：
//
//package abc;
//
//public class Hello {
//    // protected方法:
//    protected void hi() {
//    }
//}
//上面的protected方法可以被继承的类访问：
//
//package xyz;
//
//class Main extends Hello {
//    void foo() {
//        // 可以访问protected方法:
//        hi();
//    }
//}


//《package》
//最后，包作用域是指一个类允许访问同一个package的没有public、private修饰的class，以及没有public、protected、private修饰的字段和方法。
//
//package abc;
//package权限的类:
//class Hello {
//    // package权限的方法:
//    void hi() {
//    }
//}
//只要在同一个包，就可以访问package权限的class、field和method：
//
//package abc;
//
//class Main {
//    void foo() {
//        // 可以访问package权限的类:
//        Hello h = new Hello();
//        // 可以调用package权限的方法:
//        h.hi();
//    }
//}
//注意，包名必须完全一致，包没有父子关系，com.apache和com.apache.abc是不同的包。


//《局部变量》
//在方法内部定义的变量称为局部变量，局部变量作用域从变量声明处开始到对应的块结束。方法参数也是局部变量。
//
//package abc;
//
//public class Hello {
//    void hi(String name) { // ①
//        String s = name.toLowerCase(); // ②
//        int len = s.length(); // ③
//        if (len < 10) { // ④
//            int p = 10 - len; // ⑤
//            for (int i=0; i<10; i++) { // ⑥
//                System.out.println(); // ⑦
//            } // ⑧
//        } // ⑨
//    } // ⑩
//}
//我们观察上面的hi()方法代码：
//
//方法参数name是局部变量，它的作用域是整个方法，即①～⑩；
//
//变量s的作用域是定义处到方法结束，即②～⑩；
//
//变量len的作用域是定义处到方法结束，即③～⑩；
//
//变量p的作用域是定义处到if块结束，即⑤～⑨；
//
//变量i的作用域是for循环，即⑥～⑧。
//
//使用局部变量时，应该尽可能把局部变量的作用域缩小，尽可能延后声明局部变量。


//《final》
//Java还提供了一个final修饰符。final与访问权限不冲突，它有很多作用。
//
//-用final修饰class可以阻止被继承：
//package abc;
//
//// 无法被继承:
//public final class Hello {
//    private int n = 0;
//    protected void hi(int t) {
//        long i = t;
//    }
//}
//
//-用final修饰method可以阻止被子类覆写：
//
//package abc;
//
//public class Hello {
//    // 无法被覆写:
//    protected final void hi() {
//    }
//}
//
//-用final修饰field可以阻止被重新赋值：
//
//package abc;
//
//public class Hello {
//    private final int n = 0;
//    protected void hi() {
//        this.n = 1; // error!
//    }
//}
//
//-用final修饰局部变量可以阻止被重新赋值：
//
//package abc;
//
//public class Hello {
//    protected void hi(final int t) {
//        t = 1; // error!
//    }
//}

//《最佳实践》
//如果不确定是否需要public，就不声明为public，即尽可能少地暴露对外的字段和方法。
//
//把方法定义为package权限有助于测试，因为测试类和被测试类只要位于同一个package，测试代码就可以访问被测试类的package权限方法。
//
//一个.java文件只能包含一个public类，但可以包含多个非public类。如果有public类，文件名必须和public类的名字相同。


